--[[

xCT by affli @ RU-Howling Fjord
All rights reserved.
Thanks ALZA and Shestak for making this mod possible. Thanks Tukz for his wonderful style of coding. Thanks Rostok for some fixes and healing code.

Maintained by Dandruff for 4.1 and 4.2 PTR

]]--
local E, C, L = unpack(EUI)
if C["other"].xct ~= true then return end
--some init
local ct = {
    ---------------------------------------------------------------------------------
    -- use ["option"] = true/false, to set options.
    -- options
    -- blizz damage options.
        ["blizzheadnumbers"] = false, -- use blizzard damage/healing output (above mob/player head)
        ["damagestyle"]      = true,  -- change default damage/healing font above mobs/player heads. you need to restart WoW to see changes! has no effect if blizzheadnumbers = false

    -- xCT outgoing damage/healing options
        ["damage"]       = true,  -- show outgoing damage in it's own frame
        ["healing"]      = true,  -- show outgoing healing in it's own frame
        ["showhots"]     = true,  -- show periodic healing effects in xCT healing frame.
        ["damagecolor"]  = true,  -- display damage numbers depending on school of magic, see http://www.wowwiki.com/API_COMBAT_LOG_EVENT
        ["critprefix"]   = "|cffFF0000*|r", -- symbol that will be added before amount, if you deal critical strike/heal. leave "" for empty. default is red *
        ["critpostfix"]  = "|cffFF0000*|r", -- postfix symbol, "" for empty.
        ["icons"]        = true,  -- show outgoing damage icons
        ["iconsize"]     = 28,    -- icon size of spells in outgoing damage frame, also has effect on dmg font size if it's set to "auto"
        ["petdamage"]    = true,  -- show your pet damage.
        ["dotdamage"]    = true,  -- show damage from your dots. someone asked an option to disable lol.
        ["treshold"]     = 1,     -- minimum damage to show in outgoing damage frame
        ["healtreshold"] = 1,     -- minimum healing to show in incoming/outgoing healing messages.

    -- appearence
        ["font"]           = E.font, -- "Fonts\\ARIALN.ttf" is default WoW font.
        ["fontsize"]       = 16,
        ["fontstyle"]      = "OUTLINE",                           -- valid options are "OUTLINE", "MONOCHROME", "THICKOUTLINE", "OUTLINE,MONOCHROME", "THICKOUTLINE,MONOCHROME"
        ["damagefont"]     = E.font, -- "Fonts\\FRIZQT__.ttf" is default WoW damage font
        ["damagefontsize"] = "auto",                              -- size of xCT damage font. use "auto" to set it automatically depending on icon size, or use own value, 16 for example. if it's set to number value icons will change size.
        ["timevisible"]    = 3,                                   -- time (seconds) a single message will be visible. 3 is a good value.
        ["scrollable"]     = false,                               -- allows you to scroll frame lines with mousewheel.
        ["maxlines"]       = 64,                                  -- max lines to keep in scrollable mode. more lines=more memory. nom nom nom.

    -- justify messages in frames, valid values are "RIGHT" "LEFT" "CENTER"
        ["justify_1"] = "LEFT",     -- incoming damage justify
        ["justify_2"] = "RIGHT",    -- incoming healing justify
        ["justify_3"] = "CENTER",   -- various messages justify (mana, rage, auras, etc)
        ["justify_4"] = "RIGHT",    -- outgoing damage/healing justify

    -- class modules and goodies
        ["stopvespam"]       = false, -- automaticly turns off healing spam for priests in shadowform. HIDE THOSE GREEN NUMBERS PLX!
        ["dkrunes"]          = true,  -- show deatchknight rune recharge
        ["mergeaoespam"]     = true,  -- merges multiple aoe spam into single message, can be useful for dots too.
        ["mergeaoespamtime"] = 3,     -- time in seconds aoe spell will be merged into single message. minimum is 1.
        ["killingblow"]      = true,  -- tells you about your killingblows (works only with ["damage"] = true,)
        ["dispel"]           = true,  -- tells you about your dispels (works only with ["damage"] = true,)
        ["interrupt"]        = true,  -- tells you about your interrupts (works only with ["damage"] = true,)


    -- display looted items (set both to false to revert changes and go back to the original xCT)
        ["lootitems"]       = true,  -- show all looted items
        ["lootmoney"]       = true,  -- Display looted money
        
    -- fine tune loot options
        ["loothideicons"]   = true,   -- show item icons when looted
        ["looticonsize"]    = 20,    -- Icon size of looted, crafted and quest items
        ["crafteditems"]    = false, -- always show crafted items (will still show if 'lootitems' = true)
        ["questitems"]      = false, -- always show quest items (will still show if 'lootitems' = true)
        ["itemsquality"]    = 0,     -- filter items shown by item quality: 0 = Poor, 1 = Common, 2 = Uncommon, 3 = Rare, 4 = Epic, 5 = Legendary, 6 = Artifact, 7 = Heirloom
        ["itemstotal"]      = true,  -- show the total amount of items in bag ("[Epic Item Name]x1 (x23)")
        ["moneycolorblind"] = false, -- shows letters G, S, and C instead of textures
        ["minmoney"]        = 0,     -- filter money received events, less than this amount (4G 32S 12C = 43212)
}
ct.myname = UnitName("player")
ct.myclass = select(2, UnitClass("player"))
-- outgoing healing filter, hide this spammy shit, plx
if ct.healing then
    ct.healfilter = { }
    -- See class-specific config for filtered spells.
end

if ct.mergeaoespam then
    ct.aoespam = { }
    -- See class-specific config for merged spells.
end

-- class config, overrides general
if ct.myclass == "WARLOCK" then
    if ct.mergeaoespam then
        ct.aoespam[27243] = true  -- Seed of Corruption (DoT)
        ct.aoespam[27285] = true  -- Seed of Corruption (Explosion)
        ct.aoespam[87385] = true  -- Seed of Corruption (Explosion Soulburned)
        ct.aoespam[172]   = true  -- Corruption
        ct.aoespam[87389] = true  -- Corruption (Soulburn: Seed of Corruption)
        ct.aoespam[30108] = true  -- Unstable Affliction
        ct.aoespam[348]   = true  -- Immolate
        ct.aoespam[980]   = true  -- Bane of Agony
        ct.aoespam[85455] = true  -- Bane of Havoc
        ct.aoespam[85421] = true  -- Burning Embers
        ct.aoespam[42223] = true  -- Rain of Fire
        ct.aoespam[5857]  = true  -- Hellfire Effect
        ct.aoespam[47897] = true  -- Shadowflame (shadow direct damage)
        ct.aoespam[47960] = true  -- Shadowflame (fire dot)
        ct.aoespam[50590] = true  -- Immolation Aura
        ct.aoespam[30213] = true  -- Legion Strike (Felguard)
        ct.aoespam[89753] = true  -- Felstorm (Felguard)
        ct.aoespam[20153] = true  -- Immolation (Infrenal)
    end
    if ct.healing then
        ct.healfilter[28176] = true  -- Fel Armor
        ct.healfilter[63106] = true  -- Siphon Life
        ct.healfilter[54181] = true  -- Fel Synergy
        ct.healfilter[89653] = true  -- Drain Life
        ct.healfilter[79268] = true  -- Soul Harvest
        ct.healfilter[30294] = true  -- Soul Leech
    end
elseif ct.myclass == "DRUID" then
    if ct.mergeaoespam then
     -- Healer spells
        ct.aoespam[774]   = true  -- Rejuvenation (Normal)
        ct.aoespam[64801] = true  -- Rejuvenation (First tick)
        ct.aoespam[48438] = true  -- Wild Growth
        ct.aoespam[8936]  = true  -- Regrowth
        ct.aoespam[33763] = true  -- Lifebloom
        ct.aoespam[44203] = true  -- Tranquility
        ct.aoespam[81269] = true  -- Efflorescence
     -- Damager spells
        ct.aoespam[8921]  = true  -- Moonfire
        ct.aoespam[93402] = true  -- Sunfire
        ct.aoespam[5570]  = true  -- Insect Swarm
        ct.aoespam[42231] = true  -- Hurricane
        ct.aoespam[50288] = true  -- Starfall
        ct.aoespam[78777] = true  -- Wild Mushroom
        ct.aoespam[61391] = true  -- Typhoon
        ct.aoespam[1822]  = true  -- Rake
        ct.aoespam[62078] = true  -- Swipe (Cat Form)
        ct.aoespam[779]   = true  -- Swipe (Bear Form)
        ct.aoespam[33745] = true  -- Lacerate
        ct.aoespam[1079]  = true  -- Rip
    end
elseif ct.myclass == "PALADIN" then
    if ct.mergeaoespam then
        ct.aoespam[81297] = true  -- Consecration
        ct.aoespam[2812]  = true  -- Holy Wrath
        ct.aoespam[53385] = true  -- Divine Storm
        ct.aoespam[31803] = true  -- Censure
        ct.aoespam[20424] = true  -- Seals of Command
        ct.aoespam[42463] = true  -- Seal of Truth
        ct.aoespam[25742] = true  -- Seal of Righteousness
        ct.aoespam[20167] = true  -- Seal of Insight (Heal Effect)
        ct.aoespam[88263] = true  -- Hammer of the Righteous
        ct.aoespam[31935] = true  -- Avenger's Shield
        ct.aoespam[94289] = true  -- Protector of the Innocent
        ct.aoespam[53652] = true  -- Beacon of Light
        ct.aoespam[85222] = true  -- Light of Dawn        
    end
elseif ct.myclass == "PRIEST" then
    if ct.mergeaoespam then
     -- Healer spells
        ct.aoespam[47750] = true  -- Penance (Heal Effect)
        ct.aoespam[139]   = true  -- Renew
        ct.aoespam[596]   = true  -- Prayer of Healing
        ct.aoespam[56161] = true  -- Glyph of Prayer of Healing
        ct.aoespam[64844] = true  -- Divine Hymn
        ct.aoespam[32546] = true  -- Binding Heal
        ct.aoespam[77489] = true  -- Echo of Light
        ct.aoespam[34861] = true  -- Circle of Healing
        ct.aoespam[23455] = true  -- Holy Nova (Healing Effect)
        ct.aoespam[33110] = true  -- Prayer of Mending
        ct.aoespam[63544] = true  -- Divine Touch
     -- Damager spells
        ct.aoespam[47666] = true  -- Penance (Damage Effect)
        ct.aoespam[15237] = true  -- Holy Nova (Damage Effect)
        ct.aoespam[589]   = true  -- Shadow Word: Pain
        ct.aoespam[34914] = true  -- Vampiric Touch
        ct.aoespam[2944]  = true  -- Devouring Plague
        ct.aoespam[63675] = true  -- Improved Devouring Plague
        ct.aoespam[15407] = true  -- Mind Flay
        ct.aoespam[49821] = true  -- Mind Seer
        ct.aoespam[87532] = true  -- Shadowy Apparition
    end
    if ct.healing then
        ct.healfilter[2944]  = true  -- Devouring Plague (Healing)
        ct.healfilter[15290] = true  -- Vampiric Embrace
    end
elseif ct.myclass == "SHAMAN" then
    if ct.mergeaoespam then
        ct.aoespam[421]   = true  -- Chain Lightning
        ct.aoespam[8349]  = true  -- Fire Nova
        ct.aoespam[77478] = true  -- Earhquake
        ct.aoespam[51490] = true  -- Thunderstorm
        ct.aoespam[8187]  = true  -- Magma Totem
    end
    if ct.healing then
        ct.aoespam[73921] = true  -- Healing Rain
        ct.aoespam[5394]  = true  -- Healing Stream Totem
        ct.aoespam[1064]  = true  -- Chain Heal
    end
elseif ct.myclass == "MAGE" then
    if ct.mergeaoespam then
        ct.aoespam[44461] = true  -- Living Bomb Explosion
        ct.aoespam[44457] = true  -- Living Bomb Dot
        ct.aoespam[2120]  = true  -- Flamestrike
        ct.aoespam[12654] = true  -- Ignite
        ct.aoespam[11366] = true  -- Pyroblast
        ct.aoespam[31661] = true  -- Dragon's Breath
        ct.aoespam[42208] = true  -- Blizzard
        ct.aoespam[122]   = true  -- Frost Nova
        ct.aoespam[1449]  = true  -- Arcane Explosion
    end
elseif ct.myclass == "WARRIOR" then
    if ct.mergeaoespam then
        ct.aoespam[845]   = true  -- Cleave
        ct.aoespam[46968] = true  -- Shockwave
        ct.aoespam[6343]  = true  -- Thunder Clap
        ct.aoespam[1680]  = true  -- Whirlwind
        ct.aoespam[94009] = true  -- Rend
        ct.aoespam[12721] = true  -- Deep Wounds
    end
    if ct.healing then
        ct.healfilter[23880] = true  -- Bloodthirst
        ct.healfilter[55694] = true  -- Enraged Regeneration
    end
elseif ct.myclass == "HUNTER" then
    if ct.mergeaoespam then
        ct.aoespam[2643]  = true  -- Multi-Shot
        ct.aoespam[83077] = true  -- Serpent Sting (Instant Serpent Spread)
        ct.aoespam[88466] = true  -- Serpent Sting (DOT Serpent Spread)
        ct.aoespam[1978]  = true  -- Serpent Sting
        ct.aoespam[13812] = true  -- Explosive Trap  
    end
elseif ct.myclass == "DEATHKNIGHT" then
    if ct.mergeaoespam then
        ct.aoespam[55095] = true  -- Frost Fever
        ct.aoespam[55078] = true  -- Blood Plague
        ct.aoespam[55536] = true  -- Unholy Blight
        ct.aoespam[48721] = true  -- Blood Boil
        ct.aoespam[49184] = true  -- Howling Blast
        ct.aoespam[52212] = true  -- Death and Decay
    end
elseif ct.myclass == "ROGUE" then
    if ct.mergeaoespam then
        ct.aoespam[51723] = true  -- Fan of Knives
        ct.aoespam[2818]  = true  -- Deadly Poison
        ct.aoespam[8680]  = true  -- Instant Poison
    end
end


--do not edit below unless you know what you are doing
local numf
if ct.damage or ct.healing then
    numf=4
else
    numf=3
end

-- detect vechile
local function SetUnit()
    if UnitHasVehicleUI("player") then
        ct.unit = "vehicle"
    else
        ct.unit = "player"
    end
    CombatTextSetActiveUnit(ct.unit)
end

--limit lines
local function LimitLines()
    for i = 1, #ct.frames do
        f = ct.frames[i]
        f:SetMaxLines(f:GetHeight() / ct.fontsize)
    end
end

-- scrollable frames
local function SetScroll()
    for i = 1, #ct.frames do
        ct.frames[i]:EnableMouseWheel(true)
        ct.frames[i]:SetScript("OnMouseWheel", function(self, delta)
                if delta > 0 then
                    self:ScrollUp()
                elseif delta < 0 then
                    self:ScrollDown()
                end
            end)
    end
end
    
-- msg flow direction
local function ScrollDirection()
    if COMBAT_TEXT_FLOAT_MODE == "2" then
        ct.mode = "TOP"
    else
        ct.mode = "BOTTOM"
    end
    for i = 1, #ct.frames do
        ct.frames[i]:Clear()
        ct.frames[i]:SetInsertMode(ct.mode)
    end
end


-- test
-- You receive loot: |cffffffff|Hitem:22644:0:0:0:0:0:-34534534:85:0|h[Crunchy Spider Leg]|h|r x10

-- regex string for loot items
--  Example, "local pM, iQ, iI, iN, iA = select(3,string.find(msg, PAR_L_I))" returns:
--      - pM = (String)Pre-Message (e.g. "You Looted: ")
--      - iQ = (Int)Item Quality Color (e.g. FFFFFF = Common)
--      - iI = (Int)Item ID
--      - iN = (String)Item Name
--      - iA = (Int)Amount Collected (Usually blank if one)
--local PAR_L_I = "([^|]*)|?c?f?f?(%x*)|?H?[^:]*:?(-?%d+):[?(-?%d+):]+|?h?%[?([^%[%]]*)%]?|?h?|?r?%s?x?(%d*)%.?"

-- dandruff added this
local PAR_L_I = "([^|]*)|cff(%x*)|H[^:]*:(%d+):[-?%d+:]+|h%[?([^%]]*)%]|h|r?%s?x?(%d*)%.?"

-- loot events
function ChatMsgMoney_Handler(msg)
    -- Cimplex: version 1.9 beta 2 (NEED TO TEST: this in a guild run)!!!!
    local g, s, c = tonumber(msg:match("(%d+) Gold")), tonumber(msg:match("(%d+) Silver")), tonumber(msg:match("(%d+) Copper"))
    -- Cimplex>
    local money, o = (g and g * 10000 or 0) + (s and s * 100 or 0) + (c or 0), "Money:   "
    if money > ct.minmoney then
        if ct.moneycolorblind then 
            o = o..(g and g.." G   " or "")..(s and s.." S   " or "")..(c and c.." C   " or "")
        else
            o = o..GetCoinTextureString(money).."   "
        end
        if msg:find("share") then o = o.."(split)" end
        xCT3:AddMessage(o, 1, 1, 0) -- yellow
    end
end

function ChatMsgLoot_Handler(msg)
    local pM, iQ, iI, iN, iA = select(3, string.find(msg, PAR_L_I))
    local quality, _, _, itemType, _, _, _, icon = select(3, GetItemInfo(iI))
    local quest, crafted, looted, bought = (itemType == "Quest"), (pM == "You create: "), (pM == "You receive loot: "), (pM == "You receive item: ")
    if looted or bought or crafted then
        if (ct.crafteditems and crafted) or (ct.questitems and quest) or (ct.itemsquality <= quality) then
            local r, g, b = GetItemQualityColor(quality)

            -- Type and Item Name
            local s = "Received: ["..iN.."] "
            if bought then
                s = "Purchased: ["..iN.."] "
            elseif crafted then
                s = "Crafted: ["..iN.."] "
            elseif quest then
                s = "Quest Item: ["..iN.."] "
            end
		
            -- Add the Texture
            if ct.loothideicons then
                s = s.."   "
            else
                s = s.."\124T"..icon..":"..ct.looticonsize..":"..ct.looticonsize..":0:0:64:64:5:59:5:59\124t"
            end
		
            -- Amount Looted
            local amount = tonumber(iA)
            if amount and amount > 1 then
                s = s.."x"..amount
            else
                amount = 1
                s = s.."x1"
            end
		
            -- Items purchased seem to get to your bags faster than looted items
            if bought then amount = 0 end
		
            -- Total items in bag (See comment above)
            if ct.itemstotal then
                s = s.."  ("..(GetItemCount(iI) + amount).. ")"
            end
		
            -- Add the message
            xCT3:AddMessage(s, r, g, b)
        end
    end
end

-- partial resists styler
local part = "-%s (%s %s)"
local r, g, b
-- the function, handles everything
local function OnEvent(self, event, subevent, ...)
    if event == "COMBAT_TEXT_UPDATE" then
        local arg2, arg3 = ...
        if SHOW_COMBAT_TEXT == "0" then
            return
        else
            if subevent == "DAMAGE" then
                xCT1:AddMessage("-"..arg2, .75, .1, .1)
                
            elseif subevent == "DAMAGE_CRIT" then
                xCT1:AddMessage(ct.critprefix.."-"..arg2..ct.critpostfix, 1, .1, .1)
                
            elseif subevent == "SPELL_DAMAGE" then
                xCT1:AddMessage("-"..arg2, .75, .3, .85)
                
            elseif subevent == "SPELL_DAMAGE_CRIT" then
                xCT1:AddMessage(ct.critprefix.."-"..arg2..ct.critpostfix, 1, .3, .5)
                
            elseif subevent == "HEAL" then
                if arg3 >= ct.healtreshold then
                    if arg2 then
                        if COMBAT_TEXT_SHOW_FRIENDLY_NAMES == "1" then
                            xCT2:AddMessage(arg2.." +"..arg3, .1, .75, .1)
                        else
                            xCT2:AddMessage("+"..arg3, .1, .75, .1)
                        end
                    end
                end
                
            elseif subevent == "HEAL_CRIT" then
                if arg3 >= ct.healtreshold then
                    if arg2 then
                        if COMBAT_TEXT_SHOW_FRIENDLY_NAMES == "1" then
                            xCT2:AddMessage(arg2.." +"..arg3, .1, 1, .1)
                        else
                            xCT2:AddMessage("+"..arg3, .1, 1, .1)
                        end
                    end
                end
                
            elseif subevent == "PERIODIC_HEAL" then
                if arg3 >= ct.healtreshold then
                    xCT2:AddMessage("+"..arg3, .1, .5, .1)
                end

            elseif subevent == "SPELL_CAST" then
                xCT3:AddMessage(arg2, 1, .82, 0)
            
            elseif subevent == "MISS" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(MISS, .5, .5, .5)
                
            elseif subevent=="DODGE" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(DODGE, .5, .5, .5)
                
            elseif subevent=="PARRY" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(PARRY, .5, .5, .5)
                
            elseif subevent == "EVADE" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(EVADE, .5, .5, .5)
                
            elseif subevent == "IMMUNE" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(IMMUNE, .5, .5, .5)
                
            elseif subevent == "DEFLECT" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(DEFLECT, .5, .5, .5)
                
            elseif subevent == "REFLECT" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(REFLECT, .5, .5, .5)
                
            elseif subevent == "SPELL_MISS" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(MISS, .5, .5, .5)
                
            elseif subevent == "SPELL_DODGE" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(DODGE, .5, .5, .5)
                
            elseif subevent == "SPELL_PARRY" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(PARRY, .5, .5, .5)
                
            elseif subevent == "SPELL_EVADE" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(EVADE, .5, .5, .5)
                
            elseif subevent == "SPELL_IMMUNE" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(IMMUNE, .5, .5, .5)
                
            elseif subevent == "SPELL_DEFLECT" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(DEFLECT, .5, .5, .5)
                
            elseif subevent == "SPELL_REFLECT" and COMBAT_TEXT_SHOW_DODGE_PARRY_MISS == "1" then
                xCT1:AddMessage(REFLECT, .5, .5, .5)

            elseif subevent == "RESIST" then
                if arg3 then
                    if COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                        xCT1:AddMessage(part:format(arg2, RESIST, arg3), .75, .5, .5)
                    else
                        xCT1:AddMessage(arg2, .75, .1, .1)
                    end
                elseif COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                    xCT1:AddMessage(RESIST, .5, .5, .5)
                end
                
            elseif subevent == "BLOCK" then
                if arg3 then
                    if COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                        xCT1:AddMessage(part:format(arg2, BLOCK, arg3), .75, .5, .5)
                    else
                        xCT1:AddMessage(arg2, .75, .1, .1)
                    end
                elseif COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                    xCT1:AddMessage(BLOCK, .5, .5, .5)
                end
                
            elseif subevent == "ABSORB" then
                if arg3 then
                    if COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                        xCT1:AddMessage(part:format(arg2, ABSORB, arg3), .75, .5, .5)
                    else
                        xCT1:AddMessage(arg2, .75, .1, .1)
                    end
                elseif COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                    xCT1:AddMessage(ABSORB, .5, .5, .5)
                end
                
            elseif subevent == "SPELL_RESIST" then
                if arg3 then
                    if COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                        xCT1:AddMessage(part:format(arg2, RESIST, arg3), .5, .3, .5)
                    else
                        xCT1:AddMessage(arg2, .75, .3, .85)
                    end
                elseif COMBAT_TEXT_SHOW_RESISTANCES == "1"then
                    xCT1:AddMessage(RESIST, .5, .5, .5)
                end
                
            elseif subevent == "SPELL_BLOCK" then
                if arg3 then
                    if COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                        xCT1:AddMessage(part:format(arg2, BLOCK, arg3), .5, .3, .5)
                    else
                        xCT1:AddMessage("-"..arg2, .75, .3, .85)
                    end
                elseif COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                    xCT1:AddMessage(BLOCK, .5, .5, .5)
                end
                
            elseif subevent == "SPELL_ABSORB" then
                if arg3 then
                    if COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                        xCT1:AddMessage(part:format(arg2, ABSORB, arg3), .5, .3, .5)
                    else
                        xCT1:AddMessage(arg2, .75, .3, .85)
                    end
                elseif COMBAT_TEXT_SHOW_RESISTANCES == "1" then
                    xCT1:AddMessage(ABSORB, .5, .5, .5)
                end

            elseif subevent == "ENERGIZE" and COMBAT_TEXT_SHOW_ENERGIZE == "1" then
                if  tonumber(arg2) > 0 then
                    if arg3 and arg3 == "MANA" or arg3 == "RAGE" or arg3 == "FOCUS" or arg3 == "ENERGY" or arg3 == "RUINIC_POWER" or arg3 == "SOUL_SHARDS" then
                        xCT3:AddMessage("+"..arg2.." ".._G[arg3], PowerBarColor[arg3].r, PowerBarColor[arg3].g, PowerBarColor[arg3].b)
                    end
                end

            elseif subevent == "PERIODIC_ENERGIZE" and COMBAT_TEXT_SHOW_PERIODIC_ENERGIZE == "1" then
                if  tonumber(arg2) > 0 then
                    if arg3 and arg3 == "MANA" or arg3 == "RAGE" or arg3 == "FOCUS" or arg3 == "ENERGY" or arg3 == "RUINIC_POWER" or arg3 == "SOUL_SHARDS" then
                        xCT3:AddMessage("+"..arg2.." ".._G[arg3], PowerBarColor[arg3].r, PowerBarColor[arg3].g, PowerBarColor[arg3].b)
                    end
                end
                
            elseif subevent == "SPELL_AURA_START" and COMBAT_TEXT_SHOW_AURAS == "1" then
                xCT3:AddMessage("+"..arg2, 1, .5, .5)
                
            elseif subevent == "SPELL_AURA_END" and COMBAT_TEXT_SHOW_AURAS == "1" then
                xCT3:AddMessage("-"..arg2, .5, .5, .5)
                
            elseif subevent == "SPELL_AURA_START_HARMFUL" and COMBAT_TEXT_SHOW_AURAS == "1" then
                xCT3:AddMessage("+"..arg2, 1, .1, .1)
                
            elseif subevent == "SPELL_AURA_END_HARMFUL" and COMBAT_TEXT_SHOW_AURAS == "1" then
                xCT3:AddMessage("-"..arg2, .1, 1, .1)

            elseif subevent == "HONOR_GAINED" and COMBAT_TEXT_SHOW_HONOR_GAINED == "1" then
                arg2 = tonumber(arg2)
                if arg2 and abs(arg2) > 1 then
                    arg2 = floor(arg2)
                    if arg2 > 0 then
                        xCT3:AddMessage(HONOR.." +"..arg2, .1, .1, 1)
                    end
                end

            elseif subevent == "FACTION" and COMBAT_TEXT_SHOW_REPUTATION == "1" then
                xCT3:AddMessage(arg2.." +"..arg3, .1, .1, 1)

            elseif subevent == "SPELL_ACTIVE" and COMBAT_TEXT_SHOW_REACTIVES == "1" then
                xCT3:AddMessage(arg2, 1, .82, 0)
            end
        end

    elseif event == "UNIT_HEALTH" and COMBAT_TEXT_SHOW_LOW_HEALTH_MANA == "1" then
        if subevent == ct.unit then
			if COMBAT_TEXT_LOW_HEALTH_THRESHOLD then --20110715 fix error
			  if UnitHealth(ct.unit) / UnitHealthMax(ct.unit) <= COMBAT_TEXT_LOW_HEALTH_THRESHOLD then
					if not lowHealth then
						xCT3:AddMessage(HEALTH_LOW, 1, .1, .1)
						lowHealth = true
					end
				else
					lowHealth = nil
				end
			end
		end

    elseif event == "UNIT_MANA" and COMBAT_TEXT_SHOW_LOW_HEALTH_MANA == "1" then
        if subevent == ct.unit then
            local _, powerToken = UnitPowerType(ct.unit)
            if powerToken == "MANA" and UnitPower(ct.unit) / UnitPowerMax(ct.unit) <= COMBAT_TEXT_LOW_MANA_THRESHOLD then
                if not lowMana then
                    xCT3:AddMessage(MANA_LOW, 1, .1, .1)
                    lowMana = true
                end
            else
                lowMana = nil
            end
        end

    elseif event == "PLAYER_REGEN_ENABLED" and COMBAT_TEXT_SHOW_COMBAT_STATE == "1" then
            xCT3:AddMessage("-"..LEAVING_COMBAT, .1, 1, .1)

    elseif event == "PLAYER_REGEN_DISABLED" and COMBAT_TEXT_SHOW_COMBAT_STATE == "1" then
            xCT3:AddMessage("+"..ENTERING_COMBAT, 1, .1, .1)

    elseif event == "UNIT_COMBO_POINTS" and COMBAT_TEXT_SHOW_COMBO_POINTS == "1" then
        if subevent == ct.unit then
            local cp = GetComboPoints(ct.unit, "target")
                if cp > 0 then
                    r, g, b = 1, .82, .0
                    if cp == MAX_COMBO_POINTS then
                        r, g, b = 0, .82, 1
                    end
                    xCT3:AddMessage(format(COMBAT_TEXT_COMBO_POINTS, cp), r, g, b)
                end
        end

    elseif event == "RUNE_POWER_UPDATE" then
        local arg1, arg2 = subevent, ...
        if arg2 and COMBAT_TEXT_RUNE then --fix at 20110716 (COMBAT_TEXT_RUNE is nil?)
            local rune = GetRuneType(arg1);
            local msg = COMBAT_TEXT_RUNE[rune];
            if rune == 1 then 
                r, g, b = .75, 0, 0
            elseif rune==2 then
                r, g, b = .75, 1, 0
            elseif rune == 3 then
                r, g, b = 0, 1, 1  
            end
            if rune and rune < 4 then
                xCT3:AddMessage("+"..msg, r, g, b)
            end
        end

    elseif event == "UNIT_ENTERED_VEHICLE" or event == "UNIT_EXITING_VEHICLE" then
        if arg1 == "player" then
            SetUnit()
        end

    elseif event == "PLAYER_ENTERING_WORLD" then
        SetUnit()    
        if ct.scrollable then
            SetScroll()
        else
            LimitLines()
        end
        if ct.damage or ct.healing then
            ct.pguid = UnitGUID("player")
        end
		-- turn off blizz ct
 		if CombatText then
			CombatText:UnregisterAllEvents()
			CombatText:SetScript("OnLoad", nil)
			CombatText:SetScript("OnEvent", nil)
			CombatText:SetScript("OnUpdate", nil)
		end
		function E.XctMove(f)
			if E.Movers[f:GetName()]["moved"] ~= true then
				f:ClearAllPoints()
				if f:GetName() == 'xCT1' then
					f:SetPoint("CENTER", -192, -32)
				elseif f:GetName() == 'xCT2' then
					f:SetPoint("CENTER", 192, -32)
				elseif f:GetName() == 'xCT3' then
					f:SetPoint("CENTER", 0, 232)
				elseif f:GetName() == 'xCT4' then
					f:SetPoint("CENTER", 320, 0)
				end
			end
		end

		for i = 1, #ct.frames do
			local f = ct.frames[i]
			local framename
			if i == 1 then
				framename = DAMAGE
			elseif i == 2 then
				framename =SHOW_COMBAT_HEALING
			elseif i == 3 then
				framename =COMBAT_TEXT_LABEL
			elseif i == 4 then
				framename =SCORE_DAMAGE_DONE.." / "..SCORE_HEALING_DONE
			end

			E.CreateMover(f, f:GetName().."Mover", framename, nil, E.XctMove)
		end
    elseif event == "CHAT_MSG_LOOT" then
        ChatMsgLoot_Handler(subevent)
        
    elseif event == "CHAT_MSG_MONEY" then
        ChatMsgMoney_Handler(subevent)
	end
end

-- change damage font (if desired)
if ct.damagestyle then
    DAMAGE_TEXT_FONT = ct.damagefont
end

-- the frames
ct.locked = true
ct.frames = { }
for i = 1, numf do
    local f = CreateFrame("ScrollingMessageFrame", "xCT"..i, UIParent)
    f:SetFont(ct.font, ct.fontsize, ct.fontstyle)
    f:SetShadowColor(0, 0, 0, 0)
    f:SetFading(true)
    f:SetFadeDuration(0.5)
    f:SetTimeVisible(ct.timevisible)
    f:SetMaxLines(ct.maxlines)
    f:SetSpacing(2)
    f:SetWidth(128)
    f:SetHeight(128)
    f:SetPoint("CENTER", 0, 0)
    f:SetMovable(true)
    f:SetResizable(true)
    f:SetMinResize(64, 64)
    f:SetMaxResize(768, 768)
    f:SetClampedToScreen(true)
    f:SetClampRectInsets(0, 0, ct.fontsize, 0)
    if i == 1 then
        f:SetJustifyH(ct.justify_1)
        f:SetPoint("CENTER", -192, -32)
    elseif i == 2 then
        f:SetJustifyH(ct.justify_2)
       f:SetPoint("CENTER", 192, -32)
    elseif i == 3 then
        f:SetJustifyH(ct.justify_3)
        f:SetWidth(256)
       f:SetPoint("CENTER", 0, 232)
    else
        f:SetJustifyH(ct.justify_4)
       f:SetPoint("CENTER", 320, 0)
        local a, _, c = f:GetFont()
        if ct.damagefontsize == "auto" then
            if ct.icons then
                f:SetFont(a, ct.iconsize / 2, c)
            end
        elseif type(ct.damagefontsize) == "number" then
            f:SetFont(a, ct.damagefontsize, c)
        end   
    end
    ct.frames[i] = f
end

-- register events
local xCT = CreateFrame("Frame")
xCT:RegisterEvent("COMBAT_TEXT_UPDATE")
xCT:RegisterEvent("UNIT_HEALTH")
xCT:RegisterEvent("UNIT_MANA")
xCT:RegisterEvent("PLAYER_REGEN_DISABLED")
xCT:RegisterEvent("PLAYER_REGEN_ENABLED")
xCT:RegisterEvent("UNIT_COMBO_POINTS")
if ct.dkrunes and select(2, UnitClass("player")) == "DEATHKNIGHT" then
    xCT:RegisterEvent("RUNE_POWER_UPDATE")
end
xCT:RegisterEvent("UNIT_ENTERED_VEHICLE")
xCT:RegisterEvent("UNIT_EXITING_VEHICLE")
xCT:RegisterEvent("PLAYER_ENTERING_WORLD")
-- register loot events
if ct.lootitems or ct.questitems or ct.crafteditems then
    xCT:RegisterEvent("CHAT_MSG_LOOT") 
end
if ct.lootmoney then 
    xCT:RegisterEvent("CHAT_MSG_MONEY")
end

xCT:SetScript("OnEvent",OnEvent)

if CombatText then
-- turn off blizz ct
CombatText:UnregisterAllEvents()
CombatText:SetScript("OnLoad", nil)
CombatText:SetScript("OnEvent", nil)
CombatText:SetScript("OnUpdate", nil)
end
-- steal external messages sent by other addons using CombatText_AddMessage
Blizzard_CombatText_AddMessage = CombatText_AddMessage
function CombatText_AddMessage(message,scrollFunction, r, g, b, displayType, isStaggered)
    xCT3:AddMessage(message, r, g, b)
end

-- force hide blizz damage/healing, if desired
if not ct.blizzheadnumbers then
    InterfaceOptionsCombatTextPanelTargetDamage:Hide()
    InterfaceOptionsCombatTextPanelPeriodicDamage:Hide()
    InterfaceOptionsCombatTextPanelPetDamage:Hide()
    InterfaceOptionsCombatTextPanelHealing:Hide()
    SetCVar("CombatLogPeriodicSpells", 0)
    SetCVar("PetMeleeDamage", 0)
    SetCVar("CombatDamage", 0)
    SetCVar("CombatHealing", 0)
	SetCVar("enableCombatText", 1)
end

-- hook blizz float mode selector. blizz sucks, because changing  cVar combatTextFloatMode doesn't fire CVAR_UPDATE
--hooksecurefunc("InterfaceOptionsCombatTextPanelFCTDropDown_OnClick",ScrollDirection)
--COMBAT_TEXT_SCROLL_ARC="" --may cause unexpected bugs, use with caution!
InterfaceOptionsCombatTextPanelFCTDropDown:Hide() -- sorry, blizz fucking bug with SCM:SetInsertMode()

-- modify blizz ct options title lol
InterfaceOptionsCombatTextPanelTitle:SetText(COMBAT_TEXT_LABEL.." (powered by |cffFF0000x|rCT)")

-- color printer
local pr = function(msg)
    print("|cffFF0000x|rCT:", tostring(msg))
end


-- awesome shadow priest helper
if ct.stopvespam and ct.myclass == "PRIEST" then
    local sp = CreateFrame("Frame")
    sp:SetScript("OnEvent", function(...)
            if GetShapeshiftForm() == 1 then
                if ct.blizzheadnumbers then
                    SetCVar('CombatHealing', 0)
                end
            else
                if ct.blizzheadnumbers then
                    SetCVar('CombatHealing', 1)
                end
            end
        end)
    sp:RegisterEvent("PLAYER_ENTERING_WORLD")    
    sp:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
    sp:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
end

-- spam merger
local SQ
if ct.mergeaoespam then
    if ct.damage or ct.healing then
        if not ct.mergeaoespamtime or ct.mergeaoespamtime < 1 then
            ct.mergeaoespamtime = 1
        end
        local pairs = pairs
        SQ = { }
        for k, v in pairs(ct.aoespam) do
            SQ[k] = {queue = 0, msg = "", color = { }, count = 0, utime = 0, locked = false}
        end
        ct.SpamQueue=function(spellId, add)
            local amount
            local spam = SQ[spellId]["queue"]
            if spam and type(spam) == "number" then
                amount = spam + add
            else
                amount = add
            end
            return amount
        end
        local tslu = 0
        local xCTspam = CreateFrame("Frame")
        xCTspam:SetScript("OnUpdate", function(self, elapsed)
            local count
            tslu = tslu + elapsed
            if tslu > 0.5 then
                tslu = 0
            local utime = time()
                for k, v in pairs(SQ) do
                    if not SQ[k]["locked"] and SQ[k]["queue"] > 0 and SQ[k]["utime"] + ct.mergeaoespamtime <= utime then
                        if SQ[k]["count"] > 1 then
                            count = " |cffFFFFFF x "..SQ[k]["count"].."|r"
                        else
                            count = ""
                        end
                        xCT4:AddMessage(SQ[k]["queue"]..SQ[k]["msg"]..count, unpack(SQ[k]["color"]))
                        SQ[k]["queue"] = 0
                        SQ[k]["count"] = 0
                    end
                end
            end
        end)
    end
end

-- damage
if(ct.damage)then
    local unpack, select, time = unpack, select, time
    local gflags = bit.bor( COMBATLOG_OBJECT_AFFILIATION_MINE,
                            COMBATLOG_OBJECT_REACTION_FRIENDLY,
                            COMBATLOG_OBJECT_CONTROL_PLAYER,
                            COMBATLOG_OBJECT_TYPE_GUARDIAN )
                            
    local xCTd = CreateFrame("Frame")
    if ct.damagecolor then
        ct.dmgcolor = { }
        ct.dmgcolor[1]  = {  1,  1,  0 }  -- physical
        ct.dmgcolor[2]  = {  1, .9, .5 }  -- holy
        ct.dmgcolor[4]  = {  1, .5,  0 }  -- fire
        ct.dmgcolor[8]  = { .3,  1, .3 }  -- nature
        ct.dmgcolor[16] = { .5,  1,  1 }  -- frost
        ct.dmgcolor[32] = { .5, .5,  1 }  -- shadow
        ct.dmgcolor[64] = {  1, .5,  1 }  -- arcane
    end
    
    if ct.icons then
        ct.blank = E.blank
    end

    local dmg = function(self, event, ...) 
        local msg, icon
        local timestamp, eventType, dump1, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags = select(1,...)
        if (sourceGUID == ct.pguid and destGUID ~= ct.pguid) or (sourceGUID == UnitGUID("pet") and ct.petdamage) or (sourceFlags == gflags) then
            if eventType=="SWING_DAMAGE" then
                local amount, _, _, _, _, _, critical = select(10, ...)
                if amount >= ct.treshold then
                    msg = amount
                    if critical then
                        msg = ct.critprefix .. msg .. ct.critpostfix
                    end
                    if ct.icons then
                        if sourceGUID == UnitGUID("pet") or sourceFlags == gflags then
                            icon = PET_ATTACK_TEXTURE
                        else
                            icon = GetSpellTexture(6603)
                        end
                        msg = msg.." \124T"..icon..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                    end
                    xCT4:AddMessage(msg)
                end
                
            elseif eventType == "RANGE_DAMAGE" then
                local spellId, _, _, amount, _, _, _, _, _, critical = select(10, ...)
                if amount >= ct.treshold then
                    msg = amount
                    if critical then
                        msg = ct.critprefix..msg..ct.critpostfix
                    end
                    if ct.icons then
                        icon = GetSpellTexture(spellId)
                        msg = msg.." \124T"..icon..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                    end
                    xCT4:AddMessage(msg)
                end
    
            elseif eventType == "SPELL_DAMAGE" or (eventType == "SPELL_PERIODIC_DAMAGE" and ct.dotdamage) then
                local spellId, _, spellSchool, amount, _, _, _, _, _, critical = select(10, ...)
                if amount >= ct.treshold then
                    local color = { }
                    local rawamount = amount
                    if critical then
                        amount = ct.critprefix..amount..ct.critpostfix
                    end
                    if ct.icons then
                        icon = GetSpellTexture(spellId)
                    end
                    if ct.damagecolor then
                        if ct.dmgcolor[spellSchool] then
                            color = ct.dmgcolor[spellSchool]
                        else
                            color = ct.dmgcolor[1]
                        end
                    else
                        color = { 1, 1, 0 }
                    end
                    if icon then
                        msg = " \124T"..icon..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                    elseif ct.icons then
                        msg = " \124T"..ct.blank..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                    else
                        msg = ""
                    end
                    if ct.mergeaoespam and ct.aoespam[spellId] then
                        SQ[spellId]["locked"] = true
                        SQ[spellId]["queue"]  = ct.SpamQueue(spellId, rawamount)
                        SQ[spellId]["msg"]    = msg
                        SQ[spellId]["color"]  = color
                        SQ[spellId]["count"]  = SQ[spellId]["count"] + 1
                        if SQ[spellId]["count"] == 1 then
                            SQ[spellId]["utime"] = time()
                        end
                        SQ[spellId]["locked"] = false
                        return
                    end
                    xCT4:AddMessage(amount..""..msg, unpack(color))
                end
    
            elseif eventType == "SWING_MISSED" then
                local missType, _ = select(10, ...)
                if ct.icons then
                    if sourceGUID == UnitGUID("pet") or sourceFlags == gflags then
                        icon = PET_ATTACK_TEXTURE
                    else
                        icon = GetSpellTexture(6603)
                    end
                    missType = missType.." \124T"..icon..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                end
                xCT4:AddMessage(missType)
    
            elseif eventType == "SPELL_MISSED" or eventType == "RANGE_MISSED" then
                local spellId, _, _, missType, _ = select(10, ...)
                if ct.icons then
                    icon = GetSpellTexture(spellId)
                    missType = missType.." \124T"..icon..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                end 
                xCT4:AddMessage(missType)
    
            elseif eventType == "SPELL_DISPEL" and ct.dispel then
                local target, _, _, id, effect, _, etype = select(10, ...)
                local color
                if ct.icons then
                    icon = GetSpellTexture(id)
                end
                if icon then
                    msg = " \124T"..icon..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                elseif(ct.icons)then
                    msg = " \124T"..ct.blank..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                else
                    msg = ""
                end
                if etype == "BUFF"then
                    color = { 0, 1, .5 }
                else
                    color = { 1, 0, .5 }
                end
                xCT3:AddMessage(ACTION_SPELL_DISPEL..": "..effect..msg, unpack(color))
                
            elseif eventType == "SPELL_INTERRUPT" and ct.interrupt then
                local target,_, _, id, effect = select(10,...)
                local color={1,.5,0}
                if(ct.icons)then
                    icon = GetSpellTexture(id)
                end
                if icon then
                    msg = " \124T"..icon..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                elseif(ct.icons)then
                    msg = " \124T"..ct.blank..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                else
                    msg = ""
                end
                xCT3:AddMessage(ACTION_SPELL_INTERRUPT..": "..effect..msg, unpack(color))
            elseif eventType == "PARTY_KILL" and ct.killingblow then
                local tname = select(8, ...)
                xCT3:AddMessage(ACTION_PARTY_KILL..": "..tname, .2, 1, .2)
            end
            
        end
    end
    
    -- Create a Proxy event to filter unwanted arguments
    local dmg_proxy = function(self, event, timestamp, eventType, hideCaster, srcGUID, srcName, srcFlags, srcFlags2, destGUID, destName, destFlags, destFlags2, ...) 
            -- Drop srcFlags2 and destFlags2 from the arguements
            dmg(self, event, timestamp, eventType, hideCaster, srcGUID, srcName, srcFlags, destGUID, destName, destFlags, ...)
        end
    
    xCTd:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    
    if tonumber((select(4, GetBuildInfo()))) >= 40200 then
        -- this is version 4.2 or greater, call proxy
        xCTd:SetScript("OnEvent", dmg_proxy)
    else
        -- this is pre 4.2, call normal
        xCTd:SetScript("OnEvent", dmg)
    end
end

-- healing
if(ct.healing)then
    local unpack, select, time = unpack, select, time
    local xCTh = CreateFrame("Frame")
    if ct.icons then
        ct.blank = E.blank
    end
    local heal = function(self, event, ...)
        local msg, icon
        local timestamp, eventType, dump1, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags = select(1, ...)
        if sourceGUID == ct.pguid or sourceFlags == gflags then
            if eventType == 'SPELL_HEAL' or eventType == 'SPELL_PERIODIC_HEAL' and ct.showhots then
                if ct.healing then
                    local spellId, spellName, spellSchool, amount, overhealing, absorbed, critical = select(10, ...)
                    if ct.healfilter[spellId] then
                        return
                    end
                    if amount >= ct.healtreshold then
                        local color = { }
                        local rawamount = amount
                        if critical then 
                            amount = ct.critprefix..amount..ct.critpostfix
                            color = { .1, 1, .1 }
                        else
                            color = { .1, .65, .1 }
                        end 
                        if ct.icons then
                            icon = GetSpellTexture(spellId)
                        else
                            msg = ""
                        end
                        if icon then 
                            msg = ' \124T'..icon..':'..ct.iconsize..':'..ct.iconsize..':0:0:64:64:5:59:5:59\124t'
                        elseif ct.icons then
                            msg = " \124T"..ct.blank..":"..ct.iconsize..":"..ct.iconsize..":0:0:64:64:5:59:5:59\124t"
                        end
                        if ct.mergeaoespam and ct.aoespam[spellId] then
                            SQ[spellId]["locked"] = true
                            SQ[spellId]["queue"] = ct.SpamQueue(spellId, rawamount)
                            SQ[spellId]["msg"] = msg
                            SQ[spellId]["color"] = color
                            SQ[spellId]["count"] = SQ[spellId]["count"] + 1
                            if SQ[spellId]["count"] == 1 then
                                SQ[spellId]["utime"] = time()
                            end
                            SQ[spellId]["locked"] = false
                            return
                        end 
                        xCT4:AddMessage(amount..""..msg, unpack(color))
                    end
                end
            end
        end
    end
    -- Create a Proxy event to filter unwanted arguments
    local heal_proxy = function(self, event, timestamp, eventType, hideCaster, srcGUID, srcName, srcFlags, srcFlags2, destGUID, destName, destFlags, destFlags2, ...) 
            -- Drop srcFlags2 and destFlags2 from the arguements
            heal(self, event, timestamp, eventType, hideCaster, srcGUID, srcName, srcFlags, destGUID, destName, destFlags, ...)
        end
    
    xCTh:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    
    if tonumber((select(4, GetBuildInfo()))) >= 40200 then
        -- this is version 4.2 or greater, call proxy
        xCTh:SetScript("OnEvent", heal_proxy)
    else
        -- this is pre 4.2, call normal
        xCTh:SetScript("OnEvent", heal)
    end
end

